with Ada.Numerics.Long_Elementary_Functions;
use Ada.Numerics.Long_Elementary_Functions;

with Ada.Text_IO; use Ada.Text_IO;

package body Vecteurs is

   -------------------------------------------------------------------
   -- Fonctions permettant de travailler avec des vecteurs

   function New_Vecteur (X : Long_Float; Y : Long_Float) return Vecteur_Type is
      V : Vecteur_Type;
   begin
      V.X := X;
      V.Y := Y;
      return V;
   end New_Vecteur;

   function "-" (This : Vecteur_Type) return Vecteur_Type is
   begin
      return (-This.X, -This.Y);
   end "-";

   function "+" (This : Vecteur_Type; V : Vecteur_Type) return Vecteur_Type is
   begin
      return (This.X + V.X, This.Y + V.Y);
   end "+";
   pragma Inline ("+");

   procedure Add (This : in out Vecteur_Type; V : Vecteur_Type) is
   begin
      This := This + V;
   end Add;
   pragma Inline (Add);

   function "-" (This : Vecteur_Type; V : Vecteur_Type) return Vecteur_Type is
   begin
      return (This.X - V.X, This.Y - V.Y);
   end "-";
   pragma Inline ("-");

   procedure Substract (This : in out Vecteur_Type; V : Vecteur_Type) is
   begin
      This := This - V;
   end Substract;
   pragma Inline (Substract);

   function "*" (This : Vecteur_Type; Scalaire : Long_Float) return Vecteur_Type is
   begin
      return (This.X * Scalaire, This.Y * Scalaire);
   end "*";
   pragma Inline ("*");

   function "*" (Scalaire : Long_Float; This : Vecteur_Type ) return Vecteur_Type is
   begin
      return (This.X * Scalaire, This.Y * Scalaire);
   end "*";
   pragma Inline ("*");

   function "/" (This : Vecteur_Type; Nb : Long_Float ) return Vecteur_Type is
   begin
      return (This.X / Nb, This.Y / Nb);
   end "/";
   pragma Inline ("/");

   function Norme (This : Vecteur_Type) return Long_Float is
   begin
      return Sqrt (This.X * This.X + This.Y * This.Y);
   end Norme;
   pragma Inline (Norme);

   function Norme_Carre (This : Vecteur_Type) return Long_Float is
   begin
      return (This.X * This.X + This.Y * This.Y);
   end Norme_Carre;
   pragma Inline (Norme_Carre);

   procedure Normaliser (This : in out Vecteur_Type) is
   begin
      This := This / This.Norme;
   end Normaliser;


   function Scalaire (This : Vecteur_Type; V : Vecteur_Type) return Long_Float is
   begin
      return This.X * V.X + This.Y * V.Y;
   end Scalaire;
   pragma Inline (Scalaire);

   function Is_Colineaire (This, V : Vecteur_Type) return Boolean is
      X1 : Long_Float renames This.X;
      Y1 : Long_Float renames This.Y;
      X2 : Long_Float renames V.X;
      Y2 : Long_Float renames V.Y;
   begin
      if X2 = 0.0 then
         if Y2 = 0.0 then
            return False;
         else -- x2=0.0 et y2/=0.0
            return X1 = 0.0;
         end if;
      else
         if Y2 = 0.0 then
            return Y1 = 0.0;
         else
            return (X1 / X2) = (Y1 / Y2);
         end if;
      end if;
   end Is_Colineaire;

   procedure Afficher (This : Vecteur_Type) is
   begin
      Put_Line ("x=" & Long_Float'Image (This.X) & " , y=" & Long_Float'Image (This.Y));
   end Afficher;

end Vecteurs;
